from rest_framework import serializers
from meiduo_mall.utils.qq_sdk import OAuthQQ
from users.models import User
from django_redis import get_redis_connection
from .models import OauthQQUser
from rest_framework_jwt.settings import api_settings
from meiduo_mall.utils.jwt_token import get_jwt_token


class OauthQQserializer(serializers.ModelSerializer):
    """
    保存QQ用户序列化去
    """
    # write_only的目的是因为下面创建完对象返回对象的时候，序列化器会去读取这个序列化里面所有的属性，如果没写write_only而
    # 对应的模型类中(model=User)又没有这个属性，就会报错，这里写write_only与JWT里面payload中的内容没有关系，payload内的东西完全可以重写函数控制
    # 如：user模块utils中就重写了这个方法
    mobile = serializers.RegexField(regex='^1[3-9]\d{9}$', label='手机号')
    sms_code = serializers.CharField(write_only=True, label='验证码')
    access_token = serializers.CharField(write_only=True, label='操作凭证')
    token = serializers.CharField(read_only=True)

    class Meta:
        # 这个类使用的是User
        model = User
        fields = ['mobile', 'password', 'sms_code', 'access_token', 'id', 'username', 'token']

        extra_kwargs = {
            'username': {
                'read_only': True
            },
            'password': {
                'write_only': True,
                'min_length': 8,
                'max_length': 20,
                'error_messages': {
                    'mix_length': '仅允许8-20个字符的密码',
                    'max_length': '仅允许8-20个字符的密码'
                }
            }
        }

    def validate(self, attrs):
        """验证信息"""
        access_token = attrs.get('access_token')
        oauthqq = OAuthQQ()
        openid = oauthqq.check_openid_token(access_token)
        # 解密获取openid
        if not openid:
            raise serializers.ValidationError('无效的access_token')

        attrs['openid'] = openid
        # 判断验证码是否正确
        mobile = attrs.get('mobile')
        sms_code = attrs.get('sms_code')
        redis_cli = get_redis_connection('sms')
        sms_code_redis = redis_cli.get('sms_' + mobile).decode()

        if sms_code != sms_code_redis:
            raise serializers.ValidationError('验证码错误')

        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            # 这里要用pass，不能抛出异常，不然下面create方法（第一次绑定）就执行不了
            pass

        else:
            password = attrs.get('password')
            if not user.check_password(password):
                raise serializers.ValidationError('密码错误或该手机号已绑定其他账号')

            attrs['user'] = user

        return attrs

    def create(self, validated_data):
        # 这里完全可以不写，而是直接取，因为上面验证过程openid没问题的时候给attrs字典中添加了openid
        # access_token = validated_data.get('access_token')
        # oauthqq = OAuthQQ()
        # openid = oauthqq.check_openid_token(access_token)
        openid = validated_data.get('openid')
        mobile = validated_data.get('mobile')
        password = validated_data.get('password')
        # 这个user其实就是上面验证的时候添加的
        user = validated_data.get('user')

        if not user:
            # 下面这种方式创建密码加不了密
            # user = User.objects.create(username=mobile, mobile=mobile, password=password)
            user = User()
            user.username = mobile
            user.mobile = mobile
            user.set_password(password)
            user.save()

        # 创建qq用户对象
        OauthQQUser.objects.create(user=user, openid=openid)

        # 签发JWTtoken

        # jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        # jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
        # pay_load = jwt_payload_handler(user)
        # token = jwt_encode_handler(pay_load)

        user.token = get_jwt_token(user)

        return user
